/**
 * @package Infinity-Seed
 * @subpackage view
 *
 * @copyright Copyright (C) 2012-2013 Exia.CESI
 * @author Paul MAGNIN, Arthur MERCIER, Jordan RICHET, Cyril SCHUMACHER
 */
package view;

import infinity.seed.CellState;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;

/**
 * Gestion de la grille contenant les cellules.
 * @author Cyril SCHUMACHER <cyril.schumacher at viacesi.fr>
 */
public class GridCell extends JPanel {
    // <editor-fold defaultstate="collapsed" desc="Attributs.">
    /**
     * Grille contenant les cellules.
     */
    private int[][] _cellArray;
    /**
     * Taille du tableau.
     */
    private Dimension _size;
    /**
     * Taille des cases.
     */
    private Dimension _caseSize;
    /**
     * Configurations.
     */
    private infinity.seed.Configuration _configuration;
    /**
     * Nombre de case vides.
     */
    private int _emptyNumber;
    /**
     * Nombre de jeune pousses.
     */
    private int _seedNumber;
    /**
     * Nombre d'arbustes.
     */
    private int _bushNumber;
    /**
     * Nombre d'arbres.
     */
    private int _treeNumber;
    /**
     * Nombre d'infectes.
     */
    private int _infectedNumber;
    /**
     * Nombre de brules.
     */
    private int _infiredNumber;
    /**
     * Nombre de cendre.
     */
    private int _ashedNumber;
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Méthodes.">
    // <editor-fold defaultstate="collapsed" desc="Constructeur.">
    /**
     * Constructeur.
     */
    public GridCell() {
        // Initialise le nombre d'element.
        this._seedNumber = this._bushNumber = this._treeNumber = this._infectedNumber = this._infiredNumber = 0;
        // Recupere une instance de la configuration (pour les couleurs).
        this._configuration = infinity.seed.Configuration.getInstance();
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Définit la grille.">
    /**
     * Définit la grille. Provoque une ré-écriture de la grille.
     * @param cellArray Grille des cellules.
     */
    public void setGrid(int[][] cellArray) {
        this._cellArray = cellArray;
        this._size = new Dimension(cellArray.length, cellArray[0].length);
        this.paintComponent(this.getGraphics());
        this.revalidate();
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Retourne la grille avec les valeurs.">
    /**
     * Retourne la grille avec les valeurs.
     * @return Retourne la grille.
     */
    public int[][] cellArray() {
        return this._cellArray;
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Définit la dimension des cases de la grille.">
    /**
     * Définit la dimension des cases de la grille.
     * @param size Dimension en pixel.
     */
    public void setCaseSize(Dimension size) {
        this._caseSize = size;
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Retourne la dimension des cases de la grille.">
    /**
     * Retourne la dimension des cases de la grille.
     * @return Retourne la dimension.
     */
    public Dimension getCaseSize() {
        return this._caseSize;
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Analyse la grille pour compter le nombre d'élément.">
    /**
     * Analyse la grille pour compter le nombre d'élément.
     */
    private void _analyzeGrid() {
        // Initialise les valeurs.
        this._emptyNumber = this._seedNumber = this._bushNumber = this._treeNumber = this._infectedNumber = this._infiredNumber = this._ashedNumber = 0;
        
        // Parcours la grille.
        for (int i = 0; i < this._size.width; i++) {
            for (int j = 0; j < this._size.height; j++) {
                // Selon le type de la cellule, on incrémente sa variable.
                switch (this._cellArray[i][j]) {
                    case CellState.EMPTY:
                        this._emptyNumber++;
                        break;
                    case CellState.SEED:
                        this._seedNumber++;
                        break;
                    case CellState.BUSH_1:
                    case CellState.BUSH:
                        this._bushNumber++;
                        break;
                    case CellState.TREE:
                        this._treeNumber++;
                        break;
                    case CellState.SEED_INFECTED:
                    case CellState.BUSH_INFECTED:
                    case CellState.BUSH_INFECTED_1:
                    case CellState.TREE_INFECTED:
                        this._infectedNumber++;
                        break;
                    case CellState.SEED_INFIRED:
                    case CellState.BUSH_INFIRED:
                    case CellState.BUSH_INFIRED_1:
                    case CellState.TREE_INFIRED:
                        this._infiredNumber++;
                        break;
                    case CellState.ASHED:
                        this._ashedNumber++;
                        break;
                }
            }
        }
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Récupère le nombre de cellule : vide.">
    /**
     * Récupère le nombre de cellule : vide.
     * @return Retourne le nombre de jeune pousse.
     */
    public Integer getEmptyNumber() {
        return this._emptyNumber;
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Récupère le nombre de cellule : jeune pousse.">
    /**
     * Recupere le nombre de cellule : jeune pousse.
     * @return Retourne le nombre de jeune pousse.
     */
    public Integer getSeedNumber() {
        return this._seedNumber;
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Récupère le nombre de cellule : arbuste.">
    /**
     * Recupere le nombre de cellule : arbuste.
     * @return Retourne le nombre de arbuste.
     */
    public Integer getBushNumber() {
        return this._bushNumber;
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Récupère le nombre de cellule : arbre.">
    /**
     * Recupere le nombre de cellule : arbre.
     * @return Retourne le nombre de arbre.
     */
    public Integer getTreeNumber() {
        return this._treeNumber;
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Récupère le nombre de cellule : infecté.">
    /**
     * Récupère le nombre de cellule : infecté.
     * @return Retourne le nombre d'infecté.
     */
    public Integer getInfectedNumber() {
        return this._infectedNumber;
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Récupère le nombre de cellule : en feu.">
    /**
     * Recupere le nombre de cellule : en feu.
     * @return Retourne le nombre brulé.
     */
    public Integer getInfiredNumber() {
        return this._infiredNumber;
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Récupère le nombre de cellule en cendre.">
    /**
     * Récupère le nombre de cellule en cendre.
     * @return Retourne le nombre brule.
     */
    public Integer getAshedNumber() {
        return this._ashedNumber;
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Récupère la couleur de la cellule demandée.">
    /**
     * Récupère la couleur de la cellule demandée.
     * @param cell Cellule.
     * @return Retourne la couleur.
     */
    private Color _getCell(int cell) {
        // Valeur par défaut.
        String typeCell = "cell.empty";
        switch (cell) {
            // Jeune pousse.
            case CellState.SEED:
                typeCell = "cell.seed";
                break;
            // Arbuste.
            case CellState.BUSH_1:
            case CellState.BUSH:
                typeCell = "cell.bush";
                break;
            // Arbre.
            case CellState.TREE:
                typeCell = "cell.tree";
                break;
            // En feu.
            case CellState.SEED_INFIRED:
            case CellState.BUSH_INFIRED:
            case CellState.BUSH_INFIRED_1:
            case CellState.TREE_INFIRED:
                typeCell = "cell.infired";
                break;
            // Infecté.
            case CellState.SEED_INFECTED:
            case CellState.BUSH_INFECTED:
            case CellState.BUSH_INFECTED_1:
            case CellState.TREE_INFECTED:
                typeCell = "cell.infected";
                break;
            // En cendre.
            case CellState.ASHED:
                typeCell = "cell.ashed";
                break;
        }

        return Color.decode(this._configuration.get(typeCell));
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Retourne la dimension selon la taille du graphique.">
    /**
     * Retourne la dimension selon la taille du graphique. Cette méthode permet de redimensionner la grille.
     * @return Dimension Retourne la dimension.
     * @see <a href="http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html">JComponent</a>
     */
    @Override
    public Dimension getPreferredSize() {
        if ( this._cellArray.length > this._cellArray[0].length)
        {
            return new Dimension((this._cellArray[0].length * this._caseSize.width), (this._cellArray.length * this._caseSize.height));
        }
        
        else if ( this._cellArray.length < this._cellArray[0].length)
        {
            return new Dimension ((this._cellArray[0].length * this._caseSize.width), (this._cellArray.length * this._caseSize.height));
        }
        
        else
        {
            return new Dimension ((this._cellArray.length * this._caseSize.width), (this._cellArray.length * this._caseSize.height));
        }
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Dessine la grille.">
    /**
     * Dessine la grille.
     * @param g Graphique.
     * @see <a href="http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html">JComponent</a>
     */
    @Override protected void paintComponent(Graphics g) {
        // Vérifie si on peut dessiner (évite une exception NullPointerException).
        if (g != null) {
            // Classe manipulant des dessins en 2D.
            Graphics2D graph = (Graphics2D) g;
            
            // Hauteur de la grille.
            for (int i = 0; i < this._size.width; i++) {
                // Largeur de la grille.
                for (int j = 0; j < this._size.height; j++) {
                    // Recupere le type de cellule.
                    int cell = this._cellArray[i][j];

                    // Créer une case avec la couleur selon son type.
                    graph.setColor(Color.decode(_configuration.get("grid.border")));
                    graph.fillRect(j * this._caseSize.width, i * this._caseSize.width, this._caseSize.width, this._caseSize.height);
                    // Créer une case avec une bordure.
                    graph.setColor(this._getCell(cell));
                    graph.fillRect(j * this._caseSize.width, i * this._caseSize.width, this._caseSize.width - 1, this._caseSize.height - 1);
                }
            }
            
            // Libère les objets.
            graph.dispose();
            g.dispose();
            
            // Analyse la grille.
            this._analyzeGrid();
        }
    }
    // </editor-fold>
    // </editor-fold>
}
